package com.mcxx.modules.fund.service;

import cn.hutool.core.date.DateUtil;
import com.mcxx.modules.base.service.read.AreaReadService;
import com.mcxx.modules.miniSalvation.fundpay.entity.FundPayEntity;
import com.mcxx.modules.miniSalvation.fundpay.service.read.FundPayReadService;
import com.mcxx.modules.temporary.fundpay.entity.TmpFundPayEntity;
import com.mcxx.modules.temporary.fundpay.service.read.TmpFundPayReadService;
import com.mcxx.result.BaseResult;
import com.mcxx.util.AreaUtil;
import com.mcxx.util.Constant;
import com.yinhai.ta404.component.org.orguser.area.entity.TaAreaPo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import com.mcxx.redis.client.RedisClusterUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class FundPayNoTranslationService {
    @Autowired
    private FundPayService fundPayService;
    @Autowired
    private FundPayReadService fundPayReadService;
    @Autowired
    private TmpFundPayReadService tmpFundPayReadService;
    @Autowired
    private AreaReadService areaReadService;
    @Autowired
    private RedisClusterUtils redisClusterUtils;
    @Autowired
    private AreaUtil areaUtil;

    @Scheduled(cron = "0 5 0 1 * ?")
    public void autoCreateFundPayAuto(){
        Date start = new Date();
        log.info("开始创建名册");

        Calendar ca = Calendar.getInstance();
        ca.setTime(new Date());
        ca.add(Calendar.MONTH, -1);
        Date date = ca.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        String month = sdf.format(date);

        createFundPay(AreaUtil.HUNANCODE, month, null);

        log.info("创建名册完成：{},耗时{}秒", month, (new Date().getTime() - start.getTime())/1000);
    }


    public BaseResult<Boolean> createFundPay(String areaCode, String month, String businessType) {
        if(null == areaCode || areaCode.isEmpty())
            areaCode = AreaUtil.HUNANCODE;

        String validCode = areaUtil.getValidCode(areaCode);

        String[] months = month.split(",");
        Arrays.sort(months);

        BaseResult<Boolean> result = new BaseResult<Boolean>();
        result.setData(false);
        for(String curMonth : months){
            redisClusterUtils.del("genefund_"+curMonth);
            if (null != redisClusterUtils.get("genefund_"+curMonth)) {
                log.info(curMonth + "的名册已经在生成");
                result.setMsg(curMonth + "的名册已经在生成");
                return result;
            }

            redisClusterUtils.set("genefund_"+curMonth, new Date(), Constant.TIME_HALF_DAY);


            List<TaAreaPo> countys = areaReadService.getChildrenByLevel(validCode,
                    Collections.singletonList(Constant.AreaLevel.COUNTY));


            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            Date pdate = null;
            try {
                pdate = sdf.parse(curMonth + "01");
            } catch (ParseException e) {
                e.printStackTrace();
            }

            String monthFirst = DateUtil.format(pdate, "yyyy-MM-dd");
            List<FundPayEntity> allFunds = fundPayReadService.getFundPayByMonth(Constant.FundType.CAPITAL_FUND_PAY,
                    validCode, monthFirst, businessType);
            List<TmpFundPayEntity> allTmpFunds = null;
            if(null == businessType || businessType.equals(Constant.BusinessCode.LINSHI)) {
                allTmpFunds = tmpFundPayReadService.getTmpFundPayByMonth(validCode, monthFirst);
            }
            else{
                allTmpFunds = new ArrayList<>();
            }


            Map<String, List<FundPayEntity>> mapFunds
                    = allFunds.stream().collect(Collectors.groupingBy(FundPayEntity::getAreaCode));
            Map<String, List<TmpFundPayEntity>> mapTempFunds
                    = allTmpFunds.stream().collect(Collectors.groupingBy(TmpFundPayEntity::getAreaCode));


            List<String> dibaoStandards = Arrays.asList(Constant.BusinessStandType.CITY_DIBAO,
                    Constant.BusinessStandType.COUNTY_DIBAO);

            List<String> tekunStandards = Arrays.asList(Constant.BusinessStandType.CITY_TEKUN,
                    Constant.BusinessStandType.COUNTY_TEKUN);
            List<String> tekunSupplyTypes = Arrays.asList("01", "02");
            List<String> tekunCostTypes = Arrays.asList(Constant.CareFeeType.TEKUN_BASE_CODE,
                    Constant.CareFeeType.CARE_CODE);

            List<String> linshiPayWays = Arrays.asList(Constant.PayWay.BANK, Constant.PayWay.CASH, Constant.PayWay.KIND);


            for(TaAreaPo curAreaPro : countys) {
                List<FundPayEntity> funds = mapFunds.get(curAreaPro.getAreaCode());
                if(null == funds)
                    funds = new ArrayList<FundPayEntity>();


                if(null == businessType || businessType.equals(Constant.BusinessCode.DIBAO)) {
                    for(String standard : dibaoStandards){
                        Optional<FundPayEntity> fund = funds.stream().filter(
                                item -> item.getBusinessType().equals(Constant.BusinessCode.DIBAO)
                                        && item.getStandType().equals(standard)).findFirst();
                        if(!fund.isPresent()){
                            try{
                                fundPayService.addCapitalFundPay(curAreaPro.getAreaCode(), curMonth, standard,
                                                                    Constant.IsAuto.YES);
                            }
                            catch (Exception e){
                                log.error("创建低保名册异常: {}, {}, {}",
                                            curAreaPro.getAreaCode(), curMonth, standard, e);
                            }
                        }
                    }
                }


                if(null == businessType || businessType.equals(Constant.BusinessCode.TEKUN)) {
                    for(String standard : tekunStandards){
                        for(String supplyType : tekunSupplyTypes){
                            for(String costType : tekunCostTypes){
                                Optional<FundPayEntity> fund = funds.stream().filter(
                                        item -> item.getBusinessType().equals(Constant.BusinessCode.TEKUN)
                                                && item.getStandType().equals(standard)
                                                && item.getSupplyType().equals(supplyType)
                                                && item.getCostType().equals(costType)
                                ).findFirst();
                                if(!fund.isPresent()){
                                    try{
                                        fundPayService.addExCapitalFundPay(curAreaPro.getAreaCode(), curMonth, standard, supplyType,
                                                costType, Constant.IsAuto.YES);
                                    }
                                    catch (Exception e){
                                        log.error("创建特困名册异常: {}, {}, {}, {}, {}",
                                             curAreaPro.getAreaCode(),  curMonth, standard, supplyType, costType, e);
                                    }
                                }
                            }
                        }
                    }
                }


                if(null == businessType || businessType.equals(Constant.BusinessCode.LINSHI)) {
                    for(String payWay : linshiPayWays){
                        Optional<TmpFundPayEntity> fund = allTmpFunds.stream().filter(
                                item -> item.getPayWay().equals(payWay)
                                        && curAreaPro.getAreaCode().equals(item.getAreaCode())
                                        && curMonth.equals(item.getPayDate())).findFirst();
                        if(!fund.isPresent()){
                            try{
                                fundPayService.addTempFundPay(curAreaPro.getAreaCode(), curMonth, payWay,
                                                            Constant.IsAuto.YES);
                            }
                            catch (Exception e){
                                log.error("创建临时救助名册异常: {}, {}, {}",
                                        curAreaPro.getAreaCode(), curMonth, payWay, e);
                            }
                        }
                    }
                }
            }

            redisClusterUtils.del("genefund_"+curMonth);
        }

        result.setData(true);
        return result;
    }


    public BaseResult<Boolean> addProvinceFuneralFundPay(String month, String isAuto) {

        String areaCode = AreaUtil.HUNANCODE;
        String validCode = areaUtil.getValidCode(areaCode);

        String[] months = month.split(",");
        Arrays.sort(months);

        BaseResult<Boolean> result = new BaseResult<Boolean>();
        result.setData(false);

        for (String curMonth : months) {
            redisClusterUtils.del("genefund_" + curMonth + "_" + areaCode);
            if (null != redisClusterUtils.get("genefund_" + curMonth + "_" + areaCode)) {
                log.info(curMonth + "的名册已经在生成");
                result.setMsg(curMonth + "的名册已经在生成");
                return result;
            }

            redisClusterUtils.set("genefund_" + curMonth + "_" + areaCode, new Date(), Constant.TIME_HALF_DAY);


            List<TaAreaPo> areas = areaReadService.getChildrenByLevel(validCode,
                    Collections.singletonList(Constant.AreaLevel.COUNTY));


            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            Date pdate = null;
            try {
                pdate = sdf.parse(curMonth + "01");
            } catch (ParseException e) {
                e.printStackTrace();
            }

            String monthFirst = DateUtil.format(pdate, "yyyy-MM-dd");

            List<FundPayEntity> allFuneralFunds = fundPayReadService.getFundPayByMonth(Constant.FundType.FUNERAL_FUND_PAY,
                    validCode, monthFirst, null);


            Map<String, List<FundPayEntity>> mapFunds = allFuneralFunds.stream().collect(Collectors.groupingBy(FundPayEntity::getAreaCode));

            List<String> standards = Arrays.asList(Constant.BusinessStandType.CITY_TEKUN,
                    Constant.BusinessStandType.COUNTY_TEKUN);

            List<String> takeTypes = Arrays.asList(Constant.recevierType.PERSONAL,
                    Constant.recevierType.OTHER);


            for(TaAreaPo curAreaPro : areas) {
                List<FundPayEntity> funds = mapFunds.get(curAreaPro.getAreaCode());
                if (funds != null && funds.size() > 0) {
                    System.out.println(curAreaPro.getAreaCode() + ":存在丧葬费名册");
                }
                if(null == funds)
                    funds = new ArrayList<FundPayEntity>();
                if (curAreaPro.getAreaCode().startsWith("430202")) {
                    System.out.println("00000");
                }
                for(String standard : standards){
                    for(String takeType : takeTypes){
                        Optional<FundPayEntity> fund = funds.stream().filter(
                                item -> item.getStandType().equals(standard)
                                        && item.getRecevierType().equals(takeType)
                        ).findFirst();

                        if(!fund.isPresent()){
                            try{
                                fundPayService.addFuneralFundPay(curAreaPro.getAreaCode(), curMonth, standard, takeType, Constant.IsAuto.YES);
                            }
                            catch (Exception e){
                                log.error("创建丧葬费名册异常: {}, {}, {}, {}", curAreaPro.getAreaCode(),  curMonth, standard, e);
                            }
                        }
                    }
                }
            }
            redisClusterUtils.del("genefund_" + curMonth + "_" + areaCode);
        }
        result.setData(true);
        return result;
    }
}
